package com.sk.ccflower.server.common.xmlRpcManager;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.XmlRpcRequest;
import org.apache.xmlrpc.common.ServerStreamConnection;
import org.apache.xmlrpc.common.XmlRpcHttpRequestConfigImpl;
import org.apache.xmlrpc.common.XmlRpcStreamRequestConfig;
import org.apache.xmlrpc.webserver.XmlRpcServletServer;

public class MyXmlRpcServletServer extends XmlRpcServletServer
{
    protected Logger m_log = Logger.getLogger( getClass() );
    
    public MyXmlRpcServletServer() {
    	
    }
    
    /** Processes the servlet request.
     * XmlRpcServletServer의 method를 재정의
     * @param pRequest The servlet request being read.
     * @param pResponse The servlet response being created.
     * @throws IOException Reading the request or writing the response failed.
     * @throws ServletException Processing the request failed.
     */
    public void execute(HttpServletRequest pRequest, HttpServletResponse pResponse) throws ServletException, IOException {
        XmlRpcHttpRequestConfigImpl config = getConfig( pRequest );
        ServletStreamConnection ssc = newStreamConnection( pRequest, pResponse );
        
        try {
            // 원본의 아래와 같은 내용을 수정
            // super.execute(config, ssc);
        	/*
        	InputStream istream = ssc.getRequest().getInputStream();
        	BufferedReader isr = ssc.getRequest().getReader();
        	m_log.debug( "### istream.available() : "+istream.available() );
        	m_log.debug( "### isr.ready() : "+isr.ready() );
        	/*
            InputStreamReader isr = new InputStreamReader( istream, "UTF-8" );
            SAXBuilder builder = new SAXBuilder();
            Document doc = builder.build( isr );
            
            XMLOutputter xop = new XMLOutputter();
            Format format = Format.getPrettyFormat();
            format.setEncoding( "UTF-8" );
            xop.setFormat( format );
            String path = Environment.getLogDir();
            path += File.separator + "request.xml";
            OutputStream ostream = new FileOutputStream( path );
            xop.output( doc, ostream );
        	*/
            execute( config, ssc );
        } catch (XmlRpcException e) {
            throw new ServletException(e);
        } catch ( Exception e ) {
        	e.printStackTrace();
        	throw new ServletException(e);
        }
    }
    
    /** Returns, whether the
    /** Processes a "connection". The "connection" is an opaque object, which is
     * being handled by the subclasses.
     * XmlRpcStreamServer의 Method를 재정의
     * @param pConfig The request configuration.
     * @param pConnection The "connection" being processed.
     * @throws XmlRpcException Processing the request failed.
     */
    public void execute(XmlRpcStreamRequestConfig pConfig, ServerStreamConnection pConnection) throws XmlRpcException {
        boolean isManager = false;
        try {
            Object result;
            Throwable error;
            InputStream istream = null;
            try {
                istream = getInputStream(pConfig, pConnection);
                XmlRpcRequest request = getRequest(pConfig, istream);
                
                String methodName = request.getMethodName();
                m_log.debug( "getMethodName() : " + methodName );
                
                result = execute( request );
                
                istream.close();
                istream = null;
                error = null;
            } catch (Throwable t) {
                result = null;
                if(isManager==true) error = new Throwable("execute() error: " + t.getMessage());
                else error = t;
            } finally {
                if (istream != null) { try { istream.close(); } catch (Throwable ignore) {} }
            }
            
            boolean contentLengthRequired = isContentLengthRequired( pConfig );
            ByteArrayOutputStream baos;
            OutputStream ostream;
            if (contentLengthRequired) {
                baos = new ByteArrayOutputStream();
                ostream = baos;
            } else {
                baos = null;
                ostream = pConnection.newOutputStream();
            }
            ostream = getOutputStream(pConnection, pConfig, ostream);
            try {
                if (error == null) {
                	m_log.debug("execute() completed...");
                    writeResponse(pConfig, ostream, result);
                } else {
                	m_log.debug("ececute() error: " + error);
                    writeError(pConfig, ostream, error);
                }
                ostream.close();
                ostream = null;
            } finally {
                if (ostream != null) { try { ostream.close(); } catch (Throwable ignore) {} }
            }
            if (baos != null) {
                OutputStream dest = getOutputStream(pConfig, pConnection, baos.size());
                try {
                    baos.writeTo(dest);
                    dest.close();
                    dest = null;
                } finally {
                    if (dest != null) { try { dest.close(); } catch (Throwable ignore) {} }
                }
            }
            pConnection.close();
            pConnection = null;
        } catch (IOException e) {
            if(isManager) {
                throw new XmlRpcException("Error: I/O error while processing request: " + e.getMessage(), e);
            } else {
                throw new XmlRpcException("I/O error while processing request: " + e.getMessage(), e);
            }
        } finally {
            if (pConnection != null) {
            	try {
            		pConnection.close();
		            pConnection = null;
            	} catch (Throwable ignore) {
            		
            	}
            }
        }
    }
}
